package com.evil.application.service.impl;

import com.evil.application.api.RemoteApplicationStatisticsService;
import com.evil.application.enums.order.OrderQueryTypeEnum;
import com.evil.application.enums.order.StatisticsOrderTypeEnum;
import com.evil.application.enums.order.StatisticsPendingTypeEnum;
import com.evil.application.mapper.ApplicationInfoMapper;
import com.evil.application.mapper.ApplicationOrderMapper;
import com.evil.application.pojo.dto.order.OrderPageReqDTO;
import com.evil.application.pojo.dto.order.StatisticsProcessOrderDTO;
import com.evil.application.pojo.dto.order.node.OrderProcessStatisticsBO;
import com.evil.application.pojo.dto.reporting.ApplicationReportingDTO;
import com.evil.application.pojo.dto.statistics.*;
import com.evil.application.pojo.entity.ApplicationInfo;
import com.evil.application.service.ApplicationOrderService;
import com.evil.application.service.ApplicationStatisticsService;
import com.evil.common.account.dto.user.UserEnterpriseDTO;
import com.evil.common.account.util.LoginUtil;
import com.evil.common.activiti.enums.HandleTypeEnum;
import com.evil.common.application.dto.order.OrderPageDataRespDTO;
import com.evil.common.application.enums.order.OrderProcessStatusEnum;
import com.evil.common.core.entity.QueryModel;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.exception.BusinessException;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 应用统计接口
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@RestController
@RequiredArgsConstructor
public class ApplicationStatisticsServiceImpl implements ApplicationStatisticsService, RemoteApplicationStatisticsService {

    private final LoginUtil loginUtil;

    private final ApplicationOrderMapper applicationOrderMapper;

    private final ApplicationInfoMapper applicationInfoMapper;

    private final ApplicationOrderService applicationOrderService;

    /**
     * 统计登录人待办
     *
     * @param statisticsAppDataReqDTO statisticsAppDataReqDTO
     * @return StatisticsRespDTO 列表
     */
    @Override
    public List<StatisticsRespDTO> statistics(StatisticsAppDataReqDTO statisticsAppDataReqDTO) {
        UserEnterpriseDTO loginUserEnterprise = loginUtil.getLoginUserEnterprise();

        Optional<Long> appId = Optional.ofNullable(statisticsAppDataReqDTO.getApplicationKey())
                .map(e -> {
                    ApplicationInfo applicationInfo = applicationInfoMapper.isExistByKey(e)
                            .orElseThrow(() -> new BusinessException(RCodeEnum.APPLICATION_INFO_NOT_EXIST));
                    // 检查企业
                    loginUtil.checkEnterpriseId(applicationInfo.getEnterpriseId());
                    return applicationInfo.getApplicationId();
                });

        return OrderQueryTypeEnum.stream(em -> {
            StatisticsProcessOrderDTO statistics = new StatisticsProcessOrderDTO();
            statistics.setEnterpriseId(loginUserEnterprise.getEnterpriseId());
            appId.ifPresent(statistics::setApplicationId);

            ApplicationReportingDTO reportingDTO = new ApplicationReportingDTO();
            appId.ifPresent(reportingDTO::setApplicationId);

            switch (em) {
                case ALL:
                    // 草稿箱
                    statistics.setNotProcessStatus(OrderProcessStatusEnum.DRAFT_BOX.getId());
                    break;
                case SEND:
                    // 抄送事项
                    statistics.setHandleType(HandleTypeEnum.CARBON.getId());
                    statistics.setHandlers(Collections.singletonList(loginUserEnterprise.getUserId()));
                    break;
                case START:
                    // 我发起的
                    statistics.setCreatorId(loginUserEnterprise.getUserId());
                    statistics.setNotProcessStatus(OrderProcessStatusEnum.DRAFT_BOX.getId());
                    break;
                case HANDLED:
                    // 已办事项
                    statistics.setHandleTypes(HandleTypeEnum.getHandledType());
                    statistics.setHandlers(Collections.singletonList(loginUserEnterprise.getUserId()));
                    break;
                case PENDING:
                    // 待办事项
                    statistics.setHandleType(HandleTypeEnum.PROCESSING.getId());
                    statistics.setCreatorId(loginUserEnterprise.getUserId());
                    break;
                case DRAFT_BOX:
                    // 草稿箱
                    statistics.setProcessStatus(OrderProcessStatusEnum.DRAFT_BOX.getId());
                    statistics.setCreatorId(loginUserEnterprise.getUserId());
                    break;
                default:
                    throw OrderQueryTypeEnum.getBusinessException();
            }

            List<OrderProcessStatisticsBO> statisticsList = applicationOrderMapper.statisticsOrder(statistics);

            StatisticsRespDTO statisticsRespDTO = new StatisticsRespDTO();
            statisticsRespDTO.setQueryType(em.getId());
            statisticsRespDTO.setQueryTypeName(em.getName());
            statisticsRespDTO.setTotal(statisticsList.size());
            return statisticsRespDTO;
        }).collect(Collectors.toList());
    }

    /**
     * 统计登录人待办
     *
     * @return List
     */
    @Override
    public List<StatisticsPendingRespDTO> statisticsPending() {
        UserEnterpriseDTO loginUserEnterprise = loginUtil.getLoginUserEnterprise();

        return StatisticsPendingTypeEnum.stream(em -> {
            StatisticsProcessOrderDTO statistics = new StatisticsProcessOrderDTO();
            if (em == StatisticsPendingTypeEnum.ALL) {
                // 待办事项
                statistics.setHandleType(HandleTypeEnum.PROCESSING.getId());
                statistics.setHandlers(Collections.singletonList(loginUserEnterprise.getUserId()));
            }
            statistics.setEnterpriseId(loginUserEnterprise.getEnterpriseId());
            List<OrderProcessStatisticsBO> statisticsList = applicationOrderMapper.statisticsOrder(statistics);

            StatisticsPendingRespDTO statisticsPendingRespDTO = new StatisticsPendingRespDTO();
            statisticsPendingRespDTO.setOrderPendingType(em.getId());
            statisticsPendingRespDTO.setQueryType(em.getQueryTypeEnum().getId());
            statisticsPendingRespDTO.setOrderPendingTypeName(em.getName());
            statisticsPendingRespDTO.setTotal(statisticsList.size());

            return statisticsPendingRespDTO;
        }).collect(Collectors.toList());
    }

    /**
     * 登录人待办page
     *
     * @param queryModel queryModel
     * @return List
     */
    @Override
    public PageInfo<OrderPageDataRespDTO> statisticsPendingPage(QueryModel<StatisticsPendingPageReqDTO> queryModel) {
        Long loginUserId = loginUtil.getLoginUserId();
        StatisticsPendingPageReqDTO param = queryModel.getCheckParam().orElseThrow(() -> new BusinessException(RCodeEnum.ERROR_PARAMETER));

        OrderPageReqDTO orderPageReqDTO = new OrderPageReqDTO();
        orderPageReqDTO.setEnterpriseId(loginUtil.getParamEnterpriseId(param.getEnterpriseId()));
        orderPageReqDTO.setKeyword(param.getKeyword());
        orderPageReqDTO.setFuzzyQuery(param.getFuzzyQuery());
        orderPageReqDTO.setTransNumber(true);

        if (StatisticsPendingTypeEnum.isExistById(param.getStatisticsPendingType()) == StatisticsPendingTypeEnum.ALL) {
            // 待办事项
            orderPageReqDTO.addNodeHandlers(HandleTypeEnum.PROCESSING, loginUserId);
        }
        return applicationOrderService.orderList(new QueryModel<>(queryModel, orderPageReqDTO));
    }

    /**
     * 统计所有订单
     *
     * @return List
     */
    @Override
    public List<StatisticsOrderRespDTO> statisticsOrder() {
        Long loginUserId = loginUtil.getLoginUserId();

        return StatisticsOrderTypeEnum.stream(em -> {
            StatisticsProcessOrderDTO statistics = new StatisticsProcessOrderDTO();
            statistics.setEnterpriseId(loginUtil.getLoginEnterpriseId());
            switch (em) {
                case START:
                    // 我发起的
                    statistics.setCreatorId(loginUserId);
                    statistics.setNotProcessStatus(OrderProcessStatusEnum.DRAFT_BOX.getId());
                    break;
                case CARBON:
                    // 抄送事项
                    statistics.setHandleType(HandleTypeEnum.CARBON.getId());
                    statistics.setCreatorId(loginUserId);
                    break;
                case DRAFT_BOX:
                    // 草稿箱
                    statistics.setProcessStatus(OrderProcessStatusEnum.DRAFT_BOX.getId());
                    statistics.setCreatorId(loginUserId);
                    break;
                case HANDLED:
                    // 已办事项
                    statistics.setHandleTypes(HandleTypeEnum.getHandledType());
                    statistics.setHandlers(Collections.singletonList(loginUserId));
                    break;
                default:
                    throw StatisticsOrderTypeEnum.getBusinessException();
            }

            StatisticsOrderRespDTO statisticsOrder = new StatisticsOrderRespDTO();
            statisticsOrder.setStatisticsOrderType(em.getId());
            statisticsOrder.setQueryType(em.getQueryTypeEnum().getId());
            statisticsOrder.setStatisticsOrderTypeName(em.getName());
            statisticsOrder.setTotal(applicationOrderMapper.statisticsOrder(statistics).size());
            return statisticsOrder;
        }).collect(Collectors.toList());
    }

    /**
     * 登录人订单page
     *
     * @param queryModel queryModel
     * @return List
     */
    @Override
    public PageInfo<OrderPageDataRespDTO> statisticsOrderPage(QueryModel<StatisticsOrderPageReqDTO> queryModel) {
        return null;
    }

    /**
     * 统计单个app订单
     *
     * @param statisticsAppDataReqDTO statisticsAppDataReqDTO
     * @return List
     */
    @Override
    public List<StatisticsOrderRespDTO> statisticsAppOrder(StatisticsAppDataReqDTO statisticsAppDataReqDTO) {
        return null;
    }
}
